package indi.zhifa.core.multidatasource.core.factorbean;

import com.atomikos.spring.AtomikosDataSourceBean;
import com.mysql.cj.jdbc.MysqlXADataSource;
import indi.zhifa.core.multidatasource.core.RoutingDataSourceMemo;
import indi.zhifa.core.multidatasource.core.ZfRoutingDataSource;
import indi.zhifa.core.multidatasource.entity.SysDbEntity;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.boot.jdbc.DataSourceBuilder;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class MultiDataSourceFactorBean implements FactoryBean<DataSource>  {

    private final String mKey;
    private final List<SysDbEntity> mSysDbEntityList;
    private final RoutingDataSourceMemo mRoutingDataSourceMemo;

    public MultiDataSourceFactorBean(String pKey, List<SysDbEntity> pSysDbEntityList, RoutingDataSourceMemo pRoutingDataSourceMemo) {
        mKey = pKey;
        mSysDbEntityList = pSysDbEntityList;
        mRoutingDataSourceMemo = pRoutingDataSourceMemo;
    }

    @Override
    public DataSource getObject() throws Exception {
        Map<Object, Object> dataSourceMap = new HashMap<>();
        DataSource primaryDataSource = null;
        for (SysDbEntity sysDbEntity : mSysDbEntityList) {
            MysqlXADataSource dataSource = DataSourceBuilder.create().type(MysqlXADataSource.class)
                    .url(sysDbEntity.getDbUrl())
                    .username(sysDbEntity.getDbUser())
                    .password(sysDbEntity.getDbPasswd())
                    .build();
            AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
            atomikosDataSourceBean.setUniqueResourceName(sysDbEntity.getDbKey());
            atomikosDataSourceBean.setXaDataSourceClassName("com.mysql.cj.jdbc.XADataSource");
            atomikosDataSourceBean.setXaDataSource(dataSource);
            Optional.ofNullable(sysDbEntity.getMinIdle()).ifPresent(atomikosDataSourceBean::setMinPoolSize);
            Optional.ofNullable(sysDbEntity.getMaxPoolSize()).ifPresent(atomikosDataSourceBean::setMaxPoolSize);
            dataSourceMap.put(sysDbEntity.getDbKey(), atomikosDataSourceBean);
            if(sysDbEntity.getPrimary()){
                primaryDataSource = atomikosDataSourceBean;
            }
        }
        ZfRoutingDataSource dataSourceRouter = mRoutingDataSourceMemo.createRoutingDataSource(mKey,dataSourceMap,primaryDataSource);
        return dataSourceRouter;
    }

    @Override
    public Class<?> getObjectType() {
        return DataSource.class;
    }
}
